home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 32
/
Aminet 32 (1999)(Schatztruhe)[!][Aug 1999].iso
/
Aminet
/
comm
/
tcp
/
Socks5.lha
/
Socks5
/
src
/
server
/
sema.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-03-10
|
5KB
|
186 lines
/* Copyright (c) 1995-1999 NEC USA, Inc. All rights reserved. */
/* */
/* The redistribution, use and modification in source or binary forms of */
/* this software is subject to the conditions set forth in the copyright */
/* document ("Copyright") included with this distribution. */
/*
* $Id: sema.c,v 1.20.4.3 1999/02/03 22:35:42 steve Exp $
*/
#include "socks5p.h"
#include "sema.h"
#include "log.h"
#ifdef USE_SYSTEM_SEMAPHORE
#ifdef HAVE_SYS_IPC_H
#include <sys/ipc.h>
#endif
#ifdef HAVE_SYS_SEM_H
#include <sys/sem.h>
#endif
#ifndef HAVE_UNION_SEMUN
union semun { int val; struct semid_ds *buf; u_short *array; };
#endif
int semacquire(void *sem) {
struct sembuf sb = { 0, -1, SEM_UNDO };
if (sem && semop(*(int *)sem, &sb, 1) < 0) {
S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Semacquire: semop failed: %m");
return -1;
}
return 0;
}
int semrelease(void *sem) {
struct sembuf sb = { 0, 1, SEM_UNDO };
if (sem && semop(*(int *)sem, &sb, 1) < 0) {
S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Semrelease: semop failed: %m");
return -1;
}
return 0;
}
int semreset(void *sem, int val) {
/* I think semaphores with UNDO won't need resetting... */
return 0;
}
void semdestroy(void *sem) {
union semun u;
u.val = 1;
semctl(*(int *)sem, 0, IPC_RMID, u);
}
void *semcreate(int val) {
int *semid = (int *)malloc(sizeof(int));
union semun u;
u.val = val;
if (semid == NULL) {
S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Semcreate: malloc failed");
return NULL;
}
if ((*semid = semget(IPC_PRIVATE, 1, 0666)) < 0) {
S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Semcreate: semget failed: %m");
return NULL;
}
if (semctl(*semid, 0, SETVAL, u) < 0) {
S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Semcreate: semctl failed: %m");
return NULL;
}
return (void *)semid;
}
#elif defined(USE_SEMAPHORES)
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#ifdef HAVE_SYS_FILIO_H
#include <sys/filio.h>
#endif
static int semstart(S5IOHandle *fd, int count) {
if (pipe(fd) < 0) {
S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Semstart: pipe failed: %m");
return -1;
}
while (count-- > 0) semrelease((void *)fd);
return 0;
}
/* Lock (using the semaphore pipe, semfd) control of the signaling and pipes */
/* (pipe reads and writes are atomic, so the pipe can act as a semaphore.) */
int semacquire(void *sem) {
S5IOHandle *fd = (int *)sem;
char c;
if (sem && RECVSOCKET(fd[0], &c, 1, 0) < 0) {
S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Semacquire: read failed: %m");
return -1;
}
return 0;
}
/* Unlock (using the semaphore pipe) control of the signaling and pipes */
/* (pipe reads and writes are atomic, so the pipe can act as a semaphore.) */
int semrelease(void *sem) {
S5IOHandle *fd = (int *)sem;
if (sem && SENDSOCKET(fd[1], " ", 1, 0) != 1) {
S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Semrelease: write failed: %m");
return -1;
}
return 0;
}
int semreset(void *sem, int val) {
S5IOHandle *fd = (int *)sem;
int nq;
/* ok? */
if (sem == NULL) return 0;
#ifdef FIONREAD
ioctl(fd[0], FIONREAD, (char *)&nq);
if (nq == val) return 0;
#else
/* on some OSs fstat works on pipes, if it doesn't, it will return -1, */
/* and we'll be ok. */
{
struct stat sb;
if (fstat(fd[0], &sb) == 0 && sb.st_size == val) return 0;
}
#endif
/* Need to reset it, really... */
close(fd[0]);
close(fd[1]);
return semstart((int *)sem, val);
/* Since this only gets called on HUPs, we can deal with recreating the */
/* pipe -- It doesn't happen that often, and the old pipe should be */
/* gone or will be as soon as the last child that has it open exits. */
/* while (nq-- > val) semacquire(sem); while (nq++ < val) */
/* semrelease(sem); */
}
void semdestroy(void *sem) {
S5IOHandle *fd = (int *)sem;
if (!sem) return;
close(fd[0]);
close(fd[1]);
free(sem);
}
void *semcreate(int count) {
S5IOHandle *fd;
if ((fd = (int *)malloc(2 * sizeof(int)))== NULL) {
S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Semcreate: malloc failed");
return NULL;
}
semstart(fd, count);
return (void *)fd;
}
#endif /* not __svr4__ */